iT邦幫忙

0

Day57 (React)

  • 分享至 

  • xImage
  •  

1.製作元件內增加參數:

(Lab_Event > index_OK.html、index_2.html)

(1)製作元件Toggle增加屬性dataList、並更改dataList[0]

       class Toggle extends React.Component {
        constructor(props) {
          super(props);
          this.state = { 

            //兩個屬性isToggleOn、dataList
      isToggleOn: true, 
            dataList: [
              { name: "Jina" }, 
              {}, 
              {}] };

            this.state.dataList[0].name = "other peoplo"; //1.此處網頁跑完前已變更
         }

(2)預告執行程式時alert呼叫 1.data 2.dataList[0].name 3."Button clicked,顯示變更setState

         doClick = (e, data) => {
          alert(data);
          alert(this.state.dataList[0].name);
          this.setState({                          //2.顯示變更網頁使用後屬性
            isToggleOn: !this.state.isToggleOn,
          });
          alert("Button clicked.");

          // this.setState({});                     //2.顯示變更網頁使用後屬性
        };

(3)render 案到按鈕回傳

          render() {
          return (
            <button
              // 滑鼠點擊事件,data undefined,因為沒給值
              onClick={this.doClick}   

              // 執行此處 okkk > 1000 > other peoplo > Button clicked
              // 執行順序 alert("okkk")後 將值傳入(e,data)跑doClick
              onMouseLeave={(e) => {   
                alert("okkk");         
                {
                  this.doClick(e, 1000);
                }
              }}

              className="btn btn-outline-success"
            >
              {this.state.isToggleOn ? "ON" : "OFF"}
            </button>
          );
        }

Q:為何dataList[0].name改為"other peoplo"沒有setState亦變更顯示?
A:因setState作用為網頁跑完後,變更屬性時顯示變更
但此處網頁跑完前dataList[0].name已變更完畢


2.(e)必要?

(Lab_Event > index_OK.html)

        doClick = (e) => {
          // console.log(this);
          this.setState({
            isToggleOn: !this.state.isToggleOn,
          });
        };

不必要,仍可執行,但增加可以看React包裝過的event事件
但沒有e也可用使用event看event事件

        doClick = (e) => {
          console.log(this);  //Toggle {props: {…}....
          console.log(event); //此event 是傳統js 的event事件
          console.log(e); //doClick = (e)沒有e會無法顯示,此e傳入的是React 包裝過的event事件

          this.setState({
            isToggleOn: !this.state.isToggleOn,
          });
          alert("Button clicked.");
        };

https://ithelp.ithome.com.tw/upload/images/20210829/20137684If7cfku5XG.jpg


3.更改事件

(Lab_Event > index_OK.html)

onMouseLeave

        render() {
          return (
            <button onMouseLeave={this.doClick} className="btn btn-outline-success">
              {this.state.isToggleOn ? "ON" : "OFF"}
            </button>
          );
        }

onClick

        render() {
          return (
            <button onClick={this.doClick} className="btn btn-outline-success">
              {this.state.isToggleOn ? "ON" : "OFF"}
            </button>
          );
        }

4. JS - ... Spread 展開

(Lab_Event > ClassroomDemo.html、demo.html)
https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/Spread_syntax

(1)原本沒有使用...時

         var dataList = [10, 20, 30];
         var newDataList = [];
         for (let i = 0; i < dataList.length; i++) {
           var item = dataList[i]; //1.取出一個[0][1][2]
           newDataList.push(item); //2.放進來
         }
         newDataList.push(40); //3. [3]:40
         debug.innerText = newDataList.join(" | "); //10 | 20 | 30 | 40

(2)使用...

      var dataList = [10, 20, 30];

      //複製dataList[10, 20, 30]的內容 再把他解壓縮展開
      var newDataList = [...dataList, 40]; 

      debug.innerText = newDataList.join(" | "); //10 | 20 | 30 | 40

兩種結果相同,但...較簡潔

其他範例

        class Toggle extends React.Component {
        constructor(props) {
          super(props);
          this.state = { isToggleOn: true };
        }


        doClick = (e, currentToggle) => {

          //1.把舊狀態Toggle下的state拿出來,成立一個新狀態   
          let newState = { ...this.state }; 

          //2.新狀態的屬性
          newState.isToggleOn = !currentToggle; 

          //3.交給setState 顯示改變新狀態的屬性
          this.setState(newState); 

        };

5. Map 將陣列内客依序傳入處理,但需retur做回傳

(JavaScript > 05_array> Array_20_map.html)

        var data = [3, 0, 1, 8, 7, 2, 5, 4, 9, 6];       

         //map將陣列内客依序傳入,但需retur做回傳,否則map跑完,dataList的陣内容是空的
         var dataList = data.map(function (item) {
           return item + 10;
         }); //將陣列內容依序傳入 並+10

箭頭函式 (只回傳一值 => 無須{}及return)

      var dataList = data.map((aaa) => aaa + 10); //將陣列內容依序傳入 並回傳+10

同方法4.,非 => 寫法

        var dataList = data.map(function (aaa) {
          return aaa + 10;
        });

6.Props 一路演進

(Lab_Props > ClassroomDemo_a.html)

(1)製作Welcome元件

      class  extends React.Component {
        render() {
          return <h3>{this.props.name}</h3>;
        }
      }

(2)expertList為[] 此次為"資料"

      const expertList = [
        { id: 1, name: "Jeter0.5" },
        { id: 2, name: "Messi0.5" },
        { id: 3, name: "Jordan0.5" },
        { id: 4, name: "QQQ0.5" },
      ];

(3)將expertList[] 做成一個 Welcome元件

      const element3 = (
        <div>
          {expertList.map((expert) => (
            <Welcome name={expert.name} /> //Welcome元件的expertList顯示
          ))}

          <Welcome name="Jeter" />
          <Welcome name="Messi" />
          <Welcome name="Jordan" />
        </div>
      );

      ReactDOM.render(element3, document.getElementById("root"));

(4)合體(2)(3),製作新元件App

注意this.state.expertList必要,才能指定「這裡」,否則會抓到外面const expertList[]
並且return element5

      class App extends React.Component {
        constructor() {
          super();
          this.state = {
            expertList: [
              { id: 1, name: "Jeter" },
              { id: 2, name: "Messi" },
              { id: 3, name: "Jordan" },
            ],
          };
        }

        // 把element4搬進來製作element5
        render() {
          const element5 = (
            // this.state.expertList必要,才能指定「這裡」,否則會抓到外面const expertList[]
            <div>
              {this.state.expertList.map((expert) => (
                <Welcome name={expert.name} key={expert.id} />
              ))}

              <Welcome name="Jeter" />
              <Welcome name="Messi" />
              <Welcome name="Jordan" />
            </div>
          );

         // return
          return element5;
        }
      }

(5)變更(4),製作按鈕 並 增加按鈕事件toUpperCase

       class App2 extends React.Component {
        constructor() {
          super();
          this.state = {
            expertList: [
              { id: 1, name: "Jeter.App2" },
              { id: 2, name: "Messi.App2" },
              { id: 3, name: "Jordan.App2" },
            ],
          };
        }

        // 3.製作onClick事件
        doClick = () => {

          //新式寫法 有改變就變更顯示
  this.state.expertList[0].name = this.state.expertList[0].name.toUpperCase(); 
  //toUpperCase轉大寫
          this.setState({}); //網頁跑完後,變更時顯示變更屬性
        };

        render() {
          // 1. 此處清空,顯示搬到return
          // const element6 = (
          //   <div>
          //     {this.state.expertList.map((expert) => (
          //       <Welcome name={expert.name} key={expert.id} />
          //     ))}

          //     <Welcome name="Jeter.element6" />
          //     <Welcome name="Messi.element6" />
          //     <Welcome name="Jordan.element6" />
          //   </div>
          // );

          //2. return 製作按鈕 並 製作onClick事件
          return (
            <div>
              <button class="btn btn-success" onClick={this.doClick}>
                轉成大寫的按鈕
              </button>
              {this.state.expertList.map((expert) => (
                <Welcome name={expert.name} key={expert.id} />
              ))}
            </div>
          );
        }
      }

      ReactDOM.render(<App2 />, document.getElementById("root4"));

(6)接續(Lab_Props > ClassroomDemo_c.html)功能同(5)

步驟7開始為變更內容~~~~~~~~~6.前為導讀

      // 2.App元件state屬性放expertList
      class App extends React.Component {
        state = {
          expertList: [
            { id: 1, name: "Jeter" },
            { id: 2, name: "Messi" },
            { id: 3, name: "Jordan" },
          ],
        };

        // 3. 製作f,toUpperCase並且可以跑完網頁後,屬性變更時隨時變更setState
        doClick = (e) => {
          let newState = { ...this.state };
          newState.expertList[0].name = newState.expertList[0].name.toUpperCase();
          this.setState(newState);
        };

        // 12.製作刪除資料的f
        // 15.製作成箭頭函式
        doDelete = (e, id) => {
          alert("我負責刪除資料" + id);
          alert(e + id);
          //16.執行刪除的f
          var newState = { ...this.state };
          newState.expertList = newState.expertList.filter((expert) => expert.id != id);
          this.setState(newState);
        };

        // 4.回傳網頁內容讓button綁onClick滑鼠事件執行doClick
        // 5.內含f,App屬性內expertList.map方法,將[]一個一個return製作成Welcome物件(9.12.)
        render() {
          return (
            <div className="container">
              <button className="btn btn-outline-success" onClick={this.doClick}>
                Jeter toUpperCase
              </button>

              {this.state.expertList.map((expert) => (
                // 9.key是react才有的,所以多製作id={expert.id}
                // 12.製作刪除資料的屬性onDelete={this.doDelete}
     <Welcome name={expert.name} key={expert.id} id={expert.id} onDelete={this.doDelete} />
              ))}
            </div>
            // Welcome物件的name = Jeter id=1
          );
        }
      }

      // 6.Welcome回傳props屬性的name(5.給的)
      class Welcome extends React.Component {
        // 8.製作onClick事件內的f handlerDelectButtonClick
        handlerDelectButtonClick = (e) => {
          alert(this.props.key); // 10.抓不到react自己創的 所以做一個id
          alert(this.props.name);
          alert(this.props.id); // 11.抓到了
          this.props.onDelete(); //呼叫alert("我負責刪除資料"); > 此處沒給值
          this.props.onDelete(this.props.id); //13.呼叫alert("我負責刪除資料 + id"); > 此處沒給值

          this.props.onDelete(e, this.props.id); //14.傳兩個值給onDelete() 並執行;
        };

        render() {
          // JSX 外面一定要包東西,把每個東西包起來<div> 或使用 <React.Fragment>
          //return()必要,避免return;
          return (
            // 7.新增<button>及其內onClick事件
            <h3>
              {this.props.name}   {" "}
              <button onClick={this.handlerDelectButtonClick} class="btn btn-outline-danger">
                ×
              </button>
            </h3>
          );
        }
      }

      // 1.製做App元件
      // 輸出到root
      ReactDOM.render(<App></App>, document.getElementById("root"));

7. JSX 外面一定要包東西,把每個東西包起來

div 或使用 React.Fragment

      class Welcome extends React.Component {
        render() {

        //return()必要,避免return;
          return (            

            //方法1.
            // <h3>{this.props.name}</h3>

            //方法2.
            // <div>
            //   <h3>{this.props.name}</h3>我是想增加的內容
            // </div>

            //方法3.
            <React.Fragment>
              <h3>{this.props.name}</h3>我是想增加的內容
            </React.Fragment>
          );
        }
      }

8.useState 設定初值

(Lab_useState > index_0.html)

        //1. function元件製作
        function App() {

        // 2.解構賦值 let[變數, 方法]
        // useState()設定初值count=變數,setCount=方法 ,傳回陣列[]
        let [count, setCount] = React.useState(50); //count=50

        const doIncrement = () => {
          // 4.onClick事件的f
          alert("OK");
          count += 1; // 5. +1 但不會顯示
          console.log(Date());
          console.log(count);
          console.log(setCount);

          setCount(count + 1); // 6. +1 setCount似setState顯示網頁跑完之後的變更
        };
        return (
          // 3.新增buttonu並增加onClick事件
          <React.Fragment>
            <h3>count:{count}</h3>

            <button onClick={doIncrement} className="btn btn-outline-success">
              一直加上去
            </button>
          </React.Fragment>
        );
      }

連續使用setCount會錯誤
用=>讓程式可以同時進行而加二

        const handleIncrement = () => {
          // 連續使用setCount會錯誤
          // 加一? 還是加二? 加一 解決如下
          // setCount(count + 1);
          // setCount(count + 1);
          // --------------------

          // 加一? 還是加二? 加二
          // 用=>讓程式可以同時進行而加二
          setCount((previous) => previous + 1);
          setCount((previous) => previous + 1);
        };

9.解構賦值 : []給[]、{}給{}

(Lab_useState > demo02.html)

[]給[] 需照順序

      var datalist = [10, 20];
      //   var x = datalist[0];
      //   var y = datalist[1];
      var [x, y] = datalist; //解構賦值 [x, y] = [10, 20]
      alert(x + " " + y);

{}給{} 需同名資料

      var player = {
        firstName: "Jeremy",
        LastNasme: "Lin",
        unmber: 7,
      };

      //   方法1.
      //   var LastNasme = player.LastNasme;
      //   var firstName = player.firstName;

      //  方法2.使用解構賦值
      var { LastNasme, firstName } = player;

      alert(LastNasme);
      alert(firstName);

10.useEffect 副作用

變更顯示完之後,想做的事件都放在useEffect裡面

(Lab_useEffect > index_1_useEffect.html)

      // 2.製作App元件
      function App() {
        const [count, setCount] = React.useState(0);
        //const [count2, setCount2] = React.useState(0);

        // 4.變更顯示count + 1
        const doClick = () => {
          setCount(count + 1);
        };

        // 5.變更顯示完之後,想做的事件都放在useEffect裡面
        React.useEffect(() => {
          document.title = `Click count: ${count}`; //網頁名稱變更
        });
        //}, [count])

        return (
          // 3.按鈕掛上onClick事件,按下按鈕觸發doClick
          <div>
            <button onClick={doClick}>Click count: {count}</button>
          </div>
        );
      }

      // 1.render
      ReactDOM.render(<App />, document.getElementById("root"));

useEffect內的為什麼不放在doClick內? ********************************重點
因為怕程式沒跑到(連續使用setCount會錯誤)前有範例


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言